package com.seagull.core.test.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author:jian.zhou
 * @DATE: 2018/1/2.
 * @Version:0.0.1
 * @Desc:
 */
public class NioServer {


    private int blockSize = 4096 ;

    private ByteBuffer sendBuffer = ByteBuffer.allocate(blockSize);

    private ByteBuffer receiveBuffer = ByteBuffer.allocate(blockSize);

    private Selector selector;


    public NioServer ( int port ) throws IOException{

        ServerSocketChannel serverSocketChannel =  ServerSocketChannel.open();
        //是否阻塞
        serverSocketChannel.configureBlocking(false);

        ServerSocket serverSocket = serverSocketChannel.socket();

        //绑定ip 和端口
        serverSocket.bind( new InetSocketAddress(port));

        //打开选择器  接受客户端的请求
        selector = Selector.open();

        //注册一个 可接受事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println(" 服务端 已经启动 ,端口 为 " +  port) ;
        this.listen();
    }


    //监听
    public void listen () throws IOException{
        while ( true ){
            //轮询 选择器  获得事件列表
            selector.select();

            Set<SelectionKey> selectedKeys = selector.selectedKeys();

            Iterator<SelectionKey> iterator = selectedKeys.iterator();

            while ( iterator.hasNext() ){

                //获取当前事件
                SelectionKey selectionKey = iterator.next();
                iterator.remove();

                // 处理业务
                this.handleKey(selectionKey);
            }
        }
    }


    public void  handleKey ( SelectionKey selectionKey) throws IOException{
        ServerSocketChannel server = null ;
        SocketChannel client = null;
        String receiveText = "";
        String sendText = "";
        int count = 0;

        //是否 可接收事件
        if ( selectionKey.isAcceptable() ){
            server = (ServerSocketChannel) selectionKey.channel();
            //接受客户端连接
            client = server.accept();
            //是否阻塞
            client.configureBlocking(false);

            //客户端注册 一个 可读事件
            client.register(selector,SelectionKey.OP_READ);

            //如果是 读事件
        } else if ( selectionKey.isReadable() ){

            //读取 客户端数据  所有 要获得 客户端的channel
            client = (SocketChannel) selectionKey.channel();

            //把数据读取到 缓冲区
            count = client.read(receiveBuffer);
            if ( count > 0 ){
                receiveText = new String( receiveBuffer.array() ,0,count );
                System.out.println("服务端 接收到 客户端的 数据："+ receiveText);

                client.register(selector,SelectionKey.OP_WRITE);
            }

            //如果是 写事件
        } else if ( selectionKey.isWritable() ){
            //先清除 写缓冲区 数据
            sendBuffer.clear();

            //获得客户端管道
            client = ( SocketChannel) selectionKey.channel();

            sendText = " 老子在发数据 " ;
             //数据放入
            sendBuffer.put(sendText.getBytes());
            //把缓冲区数据发送出去
            sendBuffer.flip();
            client.write(sendBuffer);
            System.out.println("已经发送数据给服务端");


        }

    }


    public static void main(String[] args) {
        int port = 7080;
        try {
            NioServer nioServer = new NioServer(port);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
